package com.caishi.lkx.exam.api;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.caishi.lkx.common.AdminBaseApi;
import com.caishi.lkx.common.context.RequireContext;
import com.caishi.lkx.common.role.Roles;
import com.caishi.lkx.exam.ienum.type.ColumnType;
import com.caishi.lkx.exam.ienum.type.PackageTagType;
import com.caishi.lkx.exam.mapper.ProductBaseMapper;
import com.caishi.lkx.exam.model.*;
import com.caishi.lkx.exam.service.*;
import com.caishi.lkx.order.ienum.type.AssetsType;
import com.caishi.lkx.order.model.UserAssetsDataModel;
import com.caishi.lkx.order.service.IUserAssetsDataService;
import com.zzw.common.Wrappers;

import com.zzw.common.annotation.ApiResult;
import com.zzw.common.entity.impl.BaseEntity;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.tags.Tag;
import jodd.util.StringUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.validation.constraints.NotNull;
import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;


@Tag(name = "套餐管理")
@Slf4j
@RestController
@RequestMapping("/exam/package")
public class PackageApi extends AdminBaseApi<IPackageService, PackageModel, String> {
    @Resource
    private IPackageService packageService;
    @Resource
    private IExamService examService;
    @Resource
    private IUserAssetsDataService userAssetsDataService;

    @Resource
    private IIndustryService industryService;
    @Resource
    private IPackageTagService packageTagService;
    @Resource
    private IPackageSkuAttrService packageSkuAttrService;
    @Resource
    private IPackageSkuService packageSkuService;
    @Resource
    private IProductBaseService productBaseService;
    @Resource
    private IColumnService columnService;
    @Resource
    private ICategoryService categoryService;
    @Resource
    private IProductCodeService productCodeService;


    @Override
    public IPackageService loadService() {
        return packageService;
    }

    @Override
    @GetMapping("/page")
    @RequireContext(value = com.caishi.lkx.common.context.Role.CHANNEL)
    public IPage<PackageModel> page(@ModelAttribute Page<PackageModel> page, @ModelAttribute PackageModel model, @NotNull JSONObject otherParam) {
        if (context.getGroupId() != null) {
            model.setGroupIds(context.getGroupId().toString());
        }
//        caikuailei  43

        IPage<PackageModel> data = loadService().page(loadService().pageProcessing(page), baseWrapper(model, otherParam));
        data.setRecords(listCover(data.getRecords(), otherParam));
        return data;
    }

    @Override
    protected LambdaQueryWrapper<PackageModel> baseWrapper(PackageModel model, JSONObject otherParam) {
        return Wrappers.lambdaQuery(PackageModel.class)
                .eq(StrUtil.isNotBlank(model.getIndustryId()), PackageModel::getIndustryId, model.getIndustryId())
                .eq(StrUtil.isNotBlank(model.getExamId()), PackageModel::getExamId, model.getExamId())
                .like(StrUtil.isNotBlank(model.getName()), PackageModel::getName, model.getName())
                .like(StrUtil.isNotBlank(model.getGroupIds()), PackageModel::getGroupIds, model.getGroupIds());
    }

    @Override
    protected List<PackageModel> listCover(List<PackageModel> result, JSONObject otherParam) {
        //if (otherParam.getBool("base", false)) {
        result = result.parallelStream().peek(r -> {
            if (StrUtil.isNotBlank(r.getIndustryId())) {
                if (ExamModel.GJTK.equals(r.getIndustryId())) {
                    r.setIndustryName("高教题库");
                } else {
                    r.setIndustryName(industryService.queryName(r.getIndustryId()));
                }

            }
            if (StrUtil.isNotBlank(r.getExamId())) {
                r.setExamName(examService.queryName(r.getExamId()));
            }
            if (CollUtil.isNotEmpty(r.getTagIds())) {
                List<PackageTagModel> packageTagModels = packageTagService.selectList(Wrappers.<PackageTagModel>lambdaQuery().in(PackageTagModel::getId, r.getTagIds()));

                r.setTagNameList(packageTagModels.parallelStream().map(PackageTagModel::getName).collect(Collectors.toList()));
                r.setTagTypeList(packageTagModels.parallelStream().map(PackageTagModel::getPackageTagType).collect(Collectors.toList()));
            }
//                if (CollUtil.isNotEmpty(r.getSkuAttrIds())) {
//                    r.setSkuAttrNameList(packageSkuAttrService.getNameListByIds(r.getSkuAttrIds()));
//                }
        }).collect(Collectors.toList());
        //}

        return result;
    }

    @SneakyThrows
    @PostMapping("addOrUpdateAll")
    @Transactional(rollbackFor = Exception.class)
    public PackageModel addOrUpdateAll(@RequestParam String packageStr, @RequestParam String packageSkuStr) {
        PackageModel packageModel = JSON.parseObject(packageStr, PackageModel.class);
        if (StrUtil.isNotBlank(packageSkuStr)) {
            List<PackageSkuModel> models = JSON.parseArray(packageSkuStr, PackageSkuModel.class);
            List<String> list = models.parallelStream().filter(PackageSkuModel::getEnable).map(PackageSkuModel::getSkuAttrIds).flatMap(List::stream).toList();
            Map<String, Object> map = new HashMap<>();
            list.parallelStream().forEach(e -> {
                PackageSkuAttrModel packageSkuAttrModel = packageSkuAttrService.getById(e);
                String parentId = packageSkuAttrModel.getParentId();
                Object o = map.get(parentId);
                if (o == null) {
                    Set<String> set = new HashSet<>();
                    set.add(e);
                    map.put(parentId, set);
                } else {
                    @SuppressWarnings("unchecked")
                    Set<String> set = (HashSet<String>) o;
                    set.add(e);
                    map.put(parentId, set);
                }

            });
            packageModel.setSkuAttrs(map);
            String packageId = packageModel.getId();
            if (StrUtil.isNotBlank(packageId)) {
                this.update(packageModel);
            } else {
                this.add(packageModel);
                packageId = packageModel.getId();
            }
            packageSkuService.addOrUpdate(models, packageId);
        }

        return packageModel;
    }

    @PutMapping("/changeStatus")
    public PackageModel changeStatus(@RequestParam String id, @RequestParam Boolean enable) {
        PackageModel model = new PackageModel();
        model.setId(id);
        model.setEnable(enable);
        return super.update(model);
    }

    @PutMapping("/batch_bind_group")
    public boolean batchBindGroup(@RequestParam List<String> ids, @RequestParam String groupIds) {
        ids.forEach(id -> {
            PackageModel model = new PackageModel();
            model.setId(id);
            model.setGroupIds(groupIds);
            super.update(model);
        });
        return true;
    }

    @Operation(summary = "根据考试查询套餐列表")
    @Parameters({
            @Parameter(name = "examId", description = "考试id"),
    })
    @PostMapping("list-by-exam")
    @Transactional(rollbackFor = Exception.class)
    public List<PackageModel> listByExam(@RequestParam String examId) {
        return listCover(loadService().selectList(new LambdaQueryWrapper<PackageModel>().eq(PackageModel::getExamId, examId).eq(PackageModel::getEnable, true)), null);
    }

    ;

    //======================pc端数据查询============================
    @GetMapping("/getPackage")
    @Operation(summary = "通过考试id , 科目id, 栏目id 获取第一个满足条件的套餐信息 科目信息 skuAttr信息 ")
    @Parameters({
            @Parameter(name = "examId", description = "考试id"),
            @Parameter(name = "categoryId", description = "科目id"),
            @Parameter(name = "columnId", description = "栏目id", required = false),
    })
    @Roles
    @RequireContext(value = {com.caishi.lkx.common.context.Role.APP, com.caishi.lkx.common.context.Role.PC})
    public Map<String, Object> getPackage(@RequestParam(required = false) String examId, @RequestParam(required = false) Long categoryId, @RequestParam(required = false) String columnId) {
        if (StringUtil.isBlank(examId) && null == categoryId && StringUtil.isBlank(columnId)) {
            return null;
        }
        //产品id  通过栏目id 反查
        List<String> productIds = null;
        if (StringUtil.isNotBlank(columnId)) {
            ColumnModel column = columnService.getById(columnId);
            if (null == column) {
                return null;
            }
            categoryId = column.getCategoryId();
            List<ProductBaseModel> productBaseModels = productBaseService.selectListByColumnId(categoryId, columnId);
            if (CollUtil.isEmpty(productBaseModels)) {
                return null;
            }
            productIds = productBaseModels.stream().map(ProductBaseModel::getId).toList();
        }
        if (null != categoryId) {
            CategoryModel category = categoryService.getById(categoryId);
            examId = category.getExamId();
        }

        List<String> packageIds = packageSkuService.selectPackageIdsByExamIdAndProductIds(examId, productIds);
        if (CollUtil.isNotEmpty(packageIds)) {
            PackageModel packageModel = packageService.selectList(Wrappers.<PackageModel>lambdaQuery().in(PackageModel::getId, packageIds).eq(PackageModel::getEnable, true).like(PackageModel::getGroupIds, context.getGroupId()).orderByDesc(PackageModel::getRecommend)).get(0);

            List<PackageSkuModel> skuModels = packageSkuService.selectList(Wrappers.<PackageSkuModel>lambdaQuery()
                    .eq(PackageSkuModel::getPackageId, packageModel.getId()));
            packageModel.setSkuModels(skuModels);
            if (packageModel.getDays() != null) {
                packageModel.setEndDate(LocalDate.now().plusDays(packageModel.getDays().longValue()));
            }
            if (CollUtil.isNotEmpty(packageModel.getTagIds())) {
                List<PackageTagModel> packageTagModels = packageTagService.selectList(Wrappers.<PackageTagModel>lambdaQuery().in(PackageTagModel::getId, packageModel.getTagIds()));

                packageModel.setTagNameList(packageTagModels.parallelStream().map(PackageTagModel::getName).collect(Collectors.toList()));
                packageModel.setTagTypeList(packageTagModels.parallelStream().map(PackageTagModel::getPackageTagType).collect(Collectors.toList()));
            }
            if (ObjectUtil.isNotEmpty(packageModel)) {
                Map<String, Object> map = new HashMap<>();
                map.put("package", packageModel);
                List<CategoryModel> categoryModels = categoryService.selectList(Wrappers.<CategoryModel>lambdaQuery().eq(CategoryModel::getExamId, examId).orderByAsc(CategoryModel::getSort));
                //map.put("categorys", categoryModels);
                map.put("productIds", productIds);
//                List<PackageSkuAttrModel> skuAttrModelList = new ArrayList<>();
//                Map<String, Object> skuAttrs = packageModel.getSkuAttrs();
//                if (null != skuAttrs) {
//                    Set<String> ids = skuAttrs.keySet();
//                    skuAttrModelList = packageSkuAttrService.selectList(Wrappers.<PackageSkuAttrModel>lambdaQuery().in(PackageSkuAttrModel::getId, ids));
//                    skuAttrModelList = skuAttrModelList.parallelStream()
//                            .peek(r -> r.setChildren(packageSkuAttrService.selectList(Wrappers.<PackageSkuAttrModel>lambdaQuery().in(PackageSkuAttrModel::getId, (List<String>) skuAttrs.get(r.getId())
//                            )))).sorted(Comparator.comparingInt(PackageSkuAttrModel::getSort)).toList();
//                }
//                map.put("skuAttrs", skuAttrModelList);
                return map;
            }

        }
        return null;
    }

    @GetMapping("/getPackageByProductCode")
    @Operation(summary = "通过激活码获取套餐信息")
    @Parameters({
            @Parameter(name = "code", description = "激活码"),
    })
    public PackageSkuModel getPackageByProductCode(@RequestParam String code) {
        ProductCodeModel codeModel = productCodeService.getAndCheckByCode(code);
        PackageSkuModel skuModel = packageSkuService.getById(codeModel.getSkuId());
        List<CategoryModel> categoryModels = categoryService.selectBatchIds(skuModel.getCategoryIds());
        List<String> categoryName = categoryModels.parallelStream().map(CategoryModel::getName).toList();
        skuModel.setCategoryNameList(categoryName);
        skuModel.setExamName(examService.queryName(skuModel.getExamId()));
        skuModel.setIndustryName(industryService.queryName(skuModel.getIndustryId()));
        return skuModel;
    }

    @GetMapping("/getPackagesWithColumn")
    @RequireContext(value = {com.caishi.lkx.common.context.Role.APP, com.caishi.lkx.common.context.Role.PC})
    public List<PackageModel> getPackagesWithColumn(@RequestParam String examId, @RequestParam String columnId, @RequestParam(required = false) String categoryId) {
        Map<String, Object> params = new HashMap<>();
        params.put("examId", examId);
        params.put("enable", true);
        List<PackageModel> packages = packageService.getPackageByExam(params);
//        获取skuName
        List<String> productIds = new ArrayList<>();
        packages = packages.stream().map(r -> {
            /*tagIds不为空*/
            if(r.getTagIds()!=null&& !r.getTagIds().isEmpty()){
                QueryWrapper<PackageTagModel> wrapper = new QueryWrapper<>();
                wrapper.eq("deleted", 0)
                        .in("id", r.getTagIds())
                ;
                List<PackageTagModel> packageTagModels = packageTagService.getMapper().selectList(wrapper);
                List<String> tagNameList = new ArrayList<>();
                List<PackageTagType> tagTypeList = new ArrayList<>();
                packageTagModels.stream().forEach(packageTagModel -> {
                    tagNameList.add(packageTagModel.getName());
                    tagTypeList.add(packageTagModel.getPackageTagType());
                });
                r.setTagNameList(tagNameList);
                r.setTagTypeList(tagTypeList);
                productIds.addAll(r.getProductIds());
            }
            return r;
        }).toList();
//  获取产品对应栏目
        QueryWrapper<ProductBaseModel> wrapper = new QueryWrapper<>();
        wrapper.eq("deleted", 0)
                .in("id", productIds)
                .select("id", "column_ids")
        ;
        List<ProductBaseModel> productBaseModels = productBaseService.getMapper().selectList(wrapper);
        List<String> productBaseIds = productBaseModels.stream().filter(r -> {
            return r.getColumnIds().contains(columnId);
        }).map(BaseEntity::getId).toList();
        packages = packages.stream().filter(r -> {
            return r.getProductIds().stream().anyMatch(e -> {
                return productBaseIds.contains(e);
            });
        }).toList();

        return packages;
    }

    //    获取考试下包含某（栏目）类型的套餐,区分已购(不需要全部购买)，未买，所以已购和未买会有重复
    //   变更为某考试下 购买的某sku和未购买的sku
    @GetMapping("/list-with-column-type")
    public List<PackageModel> getPackagesWithColumnType(String examId, String types, @RequestParam(required = false, defaultValue = "false") Boolean buying) {
        List<String> typesList = Arrays.stream(types.split(",")).toList();

        Map<String, Object> params = new HashMap<>();
        params.put("examId", examId);
        params.put("enable", true);
//      套餐与sku一对多关系，返回有重复套餐id的列表
        List<PackageModel> packageByExam = packageService.getPackageByExam(params);

        List<String> productIds = new ArrayList<>();
        packageByExam.forEach(e -> {
            productIds.addAll(e.getProductIds());
        });
//        packageByExam分组去重
        packageByExam = packageByExam.stream().collect(Collectors.groupingBy(PackageModel::getId)).values().stream().map(e -> {
            if (e.size() == 1) {
                return e.get(0);
            }
            List<PackageModel> packageModels = e.subList(1, e.size());
            packageModels.forEach(ele -> {
                e.get(0).getProductIds().addAll(ele.getProductIds());
            });
            return e.get(0);
        }).toList();

        /**
         * 有的没有tagIds
         * */
        packageByExam.forEach(r -> {
            if(r.getTagIds()!=null&& !r.getTagIds().isEmpty()){
                QueryWrapper<PackageTagModel> wrapper = new QueryWrapper<>();
                wrapper.eq("deleted", 0)
                        .in("id", r.getTagIds())
                ;
                List<PackageTagModel> packageTagModels = packageTagService.getMapper().selectList(wrapper);
                List<String> tagNameList = new ArrayList<>();
                List<PackageTagType> tagTypeList = new ArrayList<>();
                packageTagModels.stream().forEach(packageTagModel -> {
                    tagNameList.add(packageTagModel.getName());
                    tagTypeList.add(packageTagModel.getPackageTagType());
                });
                r.setTagNameList(tagNameList);
                r.setTagTypeList(tagTypeList);
            }
        });

        // 去重后
        List finalProductIds = productIds.stream().collect(Collectors.toSet()).stream().toList();
        QueryWrapper<ProductBaseModel> wrapper = new QueryWrapper<>();
        wrapper.eq("deleted", 0)
                .in("id", finalProductIds)
                .select("id", "column_ids")
        ;
        // 所有套餐产品
        List<ProductBaseModel> productBaseModels = productBaseService.getMapper().selectList(wrapper);


        List<String> columnIds = new ArrayList<>();

        productBaseModels.forEach(e -> {
            columnIds.addAll(e.getColumnIds());
        });
        List finalColumnIds = columnIds.stream().collect(Collectors.toSet()).stream().toList();
        QueryWrapper<ColumnModel> wrapper1 = new QueryWrapper<>();
        wrapper1.eq("deleted", 0)
                .in("id", finalColumnIds)
                .in("type", typesList.stream().map(Integer::valueOf).toList());

        // 符合类型条件的栏目
        List<ColumnModel> columnModels = columnService.selectList(wrapper1);
//        符合条件的productBaseIds
        List<String> productBaseIds = productBaseModels.stream().filter(r -> {
            return r.getColumnIds().stream().anyMatch(v -> {
                return columnModels.stream().anyMatch(e -> {
                    return e.getId().equals(v);
                });
            });
        }).map(BaseEntity::getId).toList();


        List<PackageModel> list = packageByExam.stream().filter(e -> {
            return e.getProductIds().stream().anyMatch(ele -> {
                return productBaseIds.stream().anyMatch(v -> {
                    return v.equals(ele);
                });
            });
        }).toList();


//        可能没有对应产品
        if (productBaseIds.size() <= 0) {
            return new ArrayList<PackageModel>();
        }


        String userId = userContext.currentUserId();
        QueryWrapper<UserAssetsDataModel> wrapper2 = new QueryWrapper();
//        wrapper2.eq("user_id", userId)
//                .eq("asset_type", AssetsType.column)
//                .eq("status", true)
//                .in("asset_mapping_id", finalColumnIds);


        wrapper2.eq("user_id", userId)
                .eq("asset_type", AssetsType.product)
                .eq("status", true)
                .in("asset_mapping_id", productBaseIds);
//                .in("asset_mapping_id", finalProductIds);
        List<UserAssetsDataModel> userAssetsDataModels = userAssetsDataService.selectList(wrapper2);
//            根据产品id再次删选packageModel
        List<PackageModel> list1 = list.stream().filter(e -> {
            return e.getProductIds().stream().anyMatch(ele -> {
                return userAssetsDataModels.stream().anyMatch(v -> {
                    return v.getAssetMappingId().equals(ele);
                });
            });
        }).toList();
        if (buying) {
            return list1;
        } else {
            return list.stream().filter(e -> {
                return !(list1.stream().map(ele -> ele.getId()).toList().contains(e.getId()));
            }).toList();
        }
    }
    // 获取已购买套餐简单信息，点击跳转学习
    @ApiResult
    @GetMapping("/list-packages-with-type")
    public List<PackageModel> listPackagesWithType(String examId, String type, @RequestParam(required = false, defaultValue = "false") Boolean buying) {
        String userId = userContext.currentUserId();
        QueryWrapper<UserAssetsDataModel> wrapper2 = new QueryWrapper();
        wrapper2.eq("user_id", userId)
                .eq("asset_type", AssetsType.column)
                .eq("status", true)
                .select("asset_mapping_id", "id");
        List<UserAssetsDataModel> userAssetsDataModels = userAssetsDataService.selectList(wrapper2);

        if(userAssetsDataModels.isEmpty()){
            return new ArrayList<>();
        }

        QueryWrapper<CategoryModel> categoryWrapper = new QueryWrapper<>();
        categoryWrapper.eq("exam_id",examId)
                .eq("deleted",false);

        List<CategoryModel> categoryModels = categoryService.selectList(categoryWrapper);

        QueryWrapper<ColumnModel> columnWrapper = new QueryWrapper<>();
        columnWrapper.in("id", userAssetsDataModels.stream().map(UserAssetsDataModel::getAssetMappingId).toList())
                .in("category_id", categoryModels.stream().map(CategoryModel::getId).toList())
                .eq("deleted", false);
        if(type.equals("video")){
            columnWrapper.eq("type", ColumnType.video);
        }else if(type.equals("paperLibrary")){

        }
        // 查询已购的专栏
        List<ColumnModel> columnModels = columnService.selectList(columnWrapper);

        // 根据栏目反向获取套餐
        // 获取考试下产品
        QueryWrapper<ProductBaseModel> wrapper = new QueryWrapper<>();
        wrapper.eq("exam_id",examId)
                .eq("deleted",false);
        List<ProductBaseModel> productBaseModels = productBaseService.selectList(wrapper);
        // 过滤出包含栏目的产品
        List<ProductBaseModel> list = productBaseModels.stream().filter(productBaseModel -> {
            return productBaseModel.getColumnIds().stream().anyMatch(e -> {
                for (ColumnModel columnModel : columnModels) {
                    if (columnModel.getId().equals(e)) {
                        return true;
                    }
                }
                return false;
            });
        }).toList();
        // 获取考试下套餐
        QueryWrapper<PackageModel> packageWrapper = new QueryWrapper<>();
        List<PackageModel> packageModels = packageService.selectList(packageWrapper);
        return packageModels.stream().filter(packageModel -> {
            return packageModel.getProductIds().stream().anyMatch(productId -> {
                for (ProductBaseModel productBaseModel : list){
                    if(productBaseModel.getId().equals(productId)){
                        return true;
                    }
                }
                return false;
            });
        }).toList();
    }
}
